package com.joker.aigc.utils;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONReader;
import com.joker.aigc.jsonconvert.domain.bo.JsonToSqlBo;
import com.joker.aigc.jsonconvert.domain.dto.JsonMappingSqlDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
 * @description: json转sql工具类
 * @author: feixiang.li
 * @date: 2025-01-24 16:38
 */
@Slf4j
public class JsonToSqlUtils {


    public static final String SQL_FILE_PATH = System.getProperty("java.io.tmpdir") + File.separator;

    /**
     * json转sql
     *
     * @param jsonToSqlBo json文件
     * @return 文件路径
     */
    public static File sqlConvert(JsonToSqlBo jsonToSqlBo) {
        try {
            Assert.notNull(jsonToSqlBo, "jsonToSqlBo参数不能为空");
            Assert.notNull(jsonToSqlBo.getMultipartFile(), "文件不能为空");
            Assert.notNull(jsonToSqlBo.getColumnNames(), "列名不能为空");
            Assert.notNull(jsonToSqlBo.getSqlExecuteTypeEnum(), "sql执行类型不能为空");
            Boolean isBatch = jsonToSqlBo.getIsBatch();
            Assert.notNull(isBatch, "批量执行不能为空");
            List<JSONObject> jsonObjectList = new ArrayList<>();
            // 如果是 批量执行
            if (Boolean.TRUE.equals(isBatch)) {
                Assert.notNull(jsonToSqlBo.getBatchSize(), "批量大小不能为空");
                // 批次不能大于1000
                if (jsonToSqlBo.getBatchSize() > 1000) {
                    jsonToSqlBo.setBatchSize(1000);
                }
                if (jsonToSqlBo.getBatchSize() < 1) {
                    jsonToSqlBo.setBatchSize(100);
                }
            }
            // 创建临时文件
            File tempFile = File.createTempFile("temp", ".sql");
            FileWriter fileWriter = new FileWriter(tempFile);
            Reader inputStreamReader = null;
            if (Objects.nonNull(jsonToSqlBo.getFile())) {
                inputStreamReader = new InputStreamReader(Files.newInputStream(jsonToSqlBo.getFile().toPath()), StandardCharsets.UTF_8);
            }
            if (Objects.nonNull(jsonToSqlBo.getMultipartFile())) {
                inputStreamReader = new InputStreamReader(jsonToSqlBo.getMultipartFile().getInputStream(), StandardCharsets.UTF_8);
            }
            // 使用fastjson的流式读取
            try (JSONReader reader = new JSONReader(inputStreamReader)) {
                reader.startArray(); // 启动数组解析
                while (reader.hasNext()) {
                    // 将其解析成Map<String,Object> 类型
                    JSONObject object = (JSONObject) reader.readObject();
                    // 如果是批量执行的话，则执行
                    if (Boolean.TRUE.equals(isBatch)) {
                        jsonObjectList.add(object);
                        if (jsonObjectList.size() >= jsonToSqlBo.getBatchSize()) {
                            sqlConvertBatch(Collections.singletonList(object), jsonToSqlBo.getSqlDTOList(), jsonToSqlBo.getTableName(), fileWriter);
                            jsonObjectList = new ArrayList<>();
                        }
                    } else {
                        sqlConvert(object, jsonToSqlBo.getSqlDTOList(), jsonToSqlBo.getTableName(), fileWriter);
                    }
                }
                if (Boolean.TRUE.equals(isBatch) && !jsonObjectList.isEmpty()) {
                    sqlConvertBatch(jsonObjectList, jsonToSqlBo.getSqlDTOList(), jsonToSqlBo.getTableName(), fileWriter);
                }
                return tempFile;
            } catch (Exception e) {
                log.info("json转sql失败", e);
            } finally {
                try {
                    if (Objects.nonNull(inputStreamReader)) {
                        inputStreamReader.close();
                    }
                    fileWriter.close();
                } catch (IOException e) {
                    log.error("关闭文件失败", e);
                }
            }
        } catch (Exception e) {
            log.error("json转sql失败", e);
        }
        return null;
    }


    /**
     * sql转换
     *
     * @param jsonObject 每一个json对象
     * @param sqlDTO     json映射sql配置
     * @param tableName  表名
     * @param fileWriter 写入对象
     */
    public static void sqlConvert(JSONObject jsonObject, List<JsonMappingSqlDTO> sqlDTO, String tableName, FileWriter fileWriter) {
        if (CollUtil.isEmpty(sqlDTO) || jsonObject == null || Objects.isNull(fileWriter) || StringUtils.isEmpty(tableName)) {
            return;
        }

        StringBuilder sb = new StringBuilder();
        // 开始凭借sql
        sb.append("INSERT INTO ").append(tableName).append(" (");
        for (JsonMappingSqlDTO item : sqlDTO) {
            sb.append(item.getTo()).append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(") VALUES (");
        for (JsonMappingSqlDTO item : sqlDTO) {
            Object o = jsonObject.get(item.getFrom());
            if (Objects.isNull(o)) {
                sb.append("NULL,");
            } else {
                sb.append("'").append(o).append("',");
            }
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(");");
        // 将字符串追加到文件中
        try {
            fileWriter.write(sb.toString());
            fileWriter.write("\n");
        } catch (IOException e) {
            log.info("写入文件失败", e);
        }
    }

    public static void sqlConvertBatch(List<JSONObject> jsonObjectList, List<JsonMappingSqlDTO> sqlDTO, String tableName, FileWriter fileWriter) {
        if (CollUtil.isEmpty(sqlDTO) || CollUtil.isEmpty(jsonObjectList) || Objects.isNull(fileWriter) || StringUtils.isEmpty(tableName)) {
            return;
        }

        StringBuilder sb = new StringBuilder();
        // 开始拼接 sql
        sb.append("INSERT INTO ").append(tableName).append(" (");
        for (JsonMappingSqlDTO item : sqlDTO) {
            sb.append(item.getTo()).append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(") VALUES ");
        for (JSONObject jsonObject : jsonObjectList) {
            sb.append(getOne(jsonObject, sqlDTO));
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(");");
        // 将字符串追加到文件中
        try {
            fileWriter.write(sb.toString());
            fileWriter.write("\n");
        } catch (IOException e) {
            log.error("写入文件失败", e);
        }
    }

    public static String getOne(JSONObject jsonObject, List<JsonMappingSqlDTO> sqlDTOS) {
        StringBuilder sb = new StringBuilder();
        sb.append("(");
        for (JsonMappingSqlDTO item : sqlDTOS) {
            Object o = jsonObject.get(item.getFrom());
            if (Objects.isNull(o)) {
                sb.append("NULL,");
            } else {
                sb.append("'").append(o).append("',");
            }
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append("),");
        return sb.toString();
    }


    /**
     * 从文件中获取最大的json字段名称
     *
     * @param file 文件
     * @return 对应的json映射sql配置
     */
    public static List<JsonMappingSqlDTO> getJsonMappingSqlDTOList(File file) {
        List<JsonMappingSqlDTO> jsonMappingSqlDTOList = new ArrayList<>();
        InputStreamReader inputStreamReader = null;
        JSONReader reader = null;
        List<String> columnNames = new ArrayList<>();

        // 读取文件,读取到第一个字符串文字
        String firstLine = getFirstLine(file);

        if (StringUtils.isEmpty(firstLine)) {
            return jsonMappingSqlDTOList;
        }

        // 如果不是数组的话，则直接返回属性
        if (!StringUtils.startsWith(firstLine, "[")) {
            try {
                // 直接阅读一整个文件
                inputStreamReader = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
                reader = new JSONReader(inputStreamReader);

                // 将其解析成Map<String,Object> 类型
                JSONObject object = (JSONObject) reader.readObject();
                // 获取所有的key
                Set<String> keySet = object.keySet();
                for (String key : keySet) {
                    if (!columnNames.contains(key)) {
                        columnNames.add(key);
                        JsonMappingSqlDTO jsonMappingSqlDTO = new JsonMappingSqlDTO();
                        jsonMappingSqlDTO.setFrom(key);
                        jsonMappingSqlDTO.setTo(key);
                        String type = Optional.ofNullable(object.get(key))
                                .map(value -> value.getClass().getSimpleName())
                                .orElse("String");
                        jsonMappingSqlDTO.setType(type);
                        jsonMappingSqlDTOList.add(jsonMappingSqlDTO);

                    }
                }
            } catch (Exception e) {
                log.error("获取文件失败", e);
            } finally {
                try {
                    if (Objects.nonNull(reader)) {
                        reader.close();
                    }
                    if (Objects.nonNull(inputStreamReader)) {
                        inputStreamReader.close();
                    }
                } catch (IOException e) {
                    log.error("关闭文件失败", e);
                }
            }
            return jsonMappingSqlDTOList;
        }


        try {
            inputStreamReader = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
            reader = new JSONReader(inputStreamReader);
            reader.startArray(); // 启动数组解析
            while (reader.hasNext()) {
                // 将其解析成Map<String,Object> 类型
                JSONObject object = (JSONObject) reader.readObject();
                // 获取所有的key
                Set<String> keySet = object.keySet();
                for (String key : keySet) {
                    if (!columnNames.contains(key)) {
                        columnNames.add(key);
                        JsonMappingSqlDTO jsonMappingSqlDTO = new JsonMappingSqlDTO();
                        jsonMappingSqlDTO.setFrom(key);
                        jsonMappingSqlDTO.setTo(key);
                        String type = Optional.ofNullable(object.get(key))
                                .map(value -> value.getClass().getSimpleName())
                                .orElse("String");
                        jsonMappingSqlDTO.setType(type);
                        jsonMappingSqlDTOList.add(jsonMappingSqlDTO);
                    }
                }
            }
            reader.endArray();

        } catch (Exception e) {
            log.error("获取文件失败", e);
        } finally {

            try {
                if (Objects.nonNull(reader)) {
                    reader.close();
                }
                if (Objects.nonNull(inputStreamReader)) {
                    inputStreamReader.close();
                }
            } catch (IOException e) {
                log.error("关闭文件失败", e);
            }
        }

        return jsonMappingSqlDTOList;
    }


    public static List<List<String>> getData(File file, List<JsonMappingSqlDTO> jsonMappingSqlDTOList) {
        InputStreamReader inputStreamReader = null;
        JSONReader reader = null;

        // 如果超过20个行，则直接返回
        List<List<String>> result = new ArrayList<>();
        int i = 0;
        try {
            inputStreamReader = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
            reader = new JSONReader(inputStreamReader);
            reader.startArray(); // 启动数组解析
            while (reader.hasNext()) {
                // 将其解析成Map<String,Object> 类型
                JSONObject object = (JSONObject) reader.readObject();
                // 获取所有的key
                List<String> data = new ArrayList<>();
                for (JsonMappingSqlDTO jsonMappingSqlDTO : jsonMappingSqlDTOList) {
                    String from = jsonMappingSqlDTO.getFrom();
                    Object value = object.get(from);
                    if (Objects.nonNull(value)) {
                        data.add(value.toString());
                    } else {
                        data.add("NULL");
                    }
                }

                i++;
                if (i <=20) {
                    result.add(data);
                }
            }
            log.info("获取文件成功:{}", result);
            reader.endArray();
        } catch (Exception e) {
            log.error("获取文件失败", e);
        } finally {
            try {
                if (Objects.nonNull(reader)) {
                    reader.close();
                }
                if (Objects.nonNull(inputStreamReader)) {
                    inputStreamReader.close();
                }
            } catch (IOException e) {
                log.error("关闭文件失败", e);
            }
        }
        return result;
    }


    public static String getFirstLine(File file) {
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] words = line.trim().split("\\s+"); // 按空格分割
                if (words.length > 0 && !words[0].isEmpty()) {
                    return words[0];
                }
            }
        } catch (IOException e) {
            log.error("文件读取失败", e);
        }

        return null;
    }


    public static boolean isJson(Reader inputStreamReader) {
        try {
            JSONReader reader = new JSONReader(inputStreamReader);
            if (reader.hasNext()) {
                return true;
            }
            return false;
        } catch (JSONException e) {
            return false;
        }
    }

    /**
     * 将错误的json文件转换成正确的json文件
     *
     * @param error  错误文件
     * @param toFile 转换后的文件
     * @return 转换后的文件
     */
    public static File convertValidSql(File error, File toFile) {
        if (Objects.isNull(error) || Objects.isNull(toFile)) {
            return null;
        }
        // 如果文件不存在，则创建该文件
        FileUtil.del(toFile);
        try {
            boolean newFile = toFile.createNewFile();
            if (newFile) {
                log.info("创建文件成功");
            }
            // 使用 BufferedWriter 来进行更高效的文件写入操作
            try (BufferedWriter writer = Files.newBufferedWriter(toFile.toPath(), StandardCharsets.UTF_8, StandardOpenOption.APPEND)) {
                // 写入开始的 [
                writer.write("[ \n");

                // 读取源文件并逐行写入目标文件
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(error.toPath()), StandardCharsets.UTF_8))) {
                    String line;
                    boolean firstLine = true;  // 用于判断是否是第一行

                    while ((line = reader.readLine()) != null) {
                        line = line.trim();
                        // 去除零宽度空白字符（ZWNBSP）
//                        line = line.replaceAll("\\u200B", "");  // 使用正则替换零宽度空白字符
                        line = line.replaceAll("[\\u200B\\u200C\\u200D\\uFEFF]", ""); // 去除常见的零宽度字符

                        if (!firstLine) {
                            // 如果不是第一行，前面加上逗号
                            writer.write(",\n");
                        }
                        // 写入当前行
                        writer.write(line);
                        // 后续行不再是第一行
                        firstLine = false;
                    }
                }

                // 写入结束的 ]
                writer.write("\n]");
            }
        } catch (Exception e) {
            log.error("写入文件失败", e);

        }
        return toFile;
    }

    public static void main(String[] args) {

//        String path = "/Users/luckincoffee/Desktop/code/aigc-back/aigc-tools/src/main/resources/test.json";

        String path = "/Users/luckincoffee/Desktop/code/aigc-back/aigc-tools/src/main/resources/2.json";

//        String toPath = "/Users/luckincoffee/Desktop/code/aigc-back/aigc-tools/src/main/resources/test1.json";

//        File file = convertValidSql(path, toPath);
        File file = new File(path);
        List<JsonMappingSqlDTO> jsonMappingSqlDTOList = getJsonMappingSqlDTOList(file);

        for (JsonMappingSqlDTO jsonMappingSqlDTO : jsonMappingSqlDTOList) {
            System.out.println(jsonMappingSqlDTO);
        }
//
//        JsonToSqlBo jsonToSqlBo = new JsonToSqlBo();
//
//        jsonToSqlBo.setTableName("test");


    }
}
